﻿// HSS.Interlink.Web.FileQuery.cs
// ----------------------------------------------------------------------------
// Licensed under the MIT license (http://www.opensource.org/licenses/mit-license.html)
// ----------------------------------------------------------------------------
// HighSpeed-Solutions, LLC
// Copyright (c) 2001-2012
// ----------------------------------------------------------------------------
// File:       FileQuery.cs
// Author:     HSS\gbanta
// Created:    07/16/2011
// Modified:   07/22/2011
// ----------------------------------------------------------------------------
namespace HSS.Interlink.Web
{
	#region Using Directives
	using System;
	using System.Collections.Specialized;
	using System.Text;
	using System.Web;
	using System.Globalization;
	#endregion

	#region FileQuery
	/// <summary>
	/// Contains the parts of the request query string.
	/// </summary>
	public sealed class FileQuery
	{
		#region Constructors
		/// <summary>
		/// Constructor
		/// </summary>
		private FileQuery()
		{

		}
		#endregion

		#region Properties
		/// <summary>
		/// Gets the JobId of the current request
		/// </summary>
		public Guid JobId
		{
			get;
			internal set;
		}
		/// <summary>
		/// Gets the name of the client File being uploaded or downloaded.
		/// </summary>
		public string FileName
		{
			get;
			internal set;
		}
		/// <summary>
		/// Gets the current <see cref="FileQueryCommand"/>.
		/// </summary>
		public FileQueryCommand Command
		{
			get;
			internal set;
		}
		/// <summary>
		/// Gets the requested appsetting key of your file Handler.
		/// </summary>
		public string HandlerKey
		{
			get;
			internal set;
		}
		/// <summary>
		/// Gets the timestamp of the request, expressed as UTC Time.
		/// </summary>
		public DateTime TimestampUtc
		{
			get;
			internal set;
		}
		/// <summary>
		/// Gets if the request is for a PING test.
		/// </summary>
		public bool IsPing { get; private set; }
		#endregion

		#region Methods
		internal static FileQuery ParseRequestQuery(string rawQuery)
		{
			var query = new FileQuery();
			if (!string.IsNullOrEmpty(rawQuery))
			{
				if (rawQuery.Equals("ping", StringComparison.InvariantCultureIgnoreCase))
					return new FileQuery() { IsPing = true };
				var raw = DecodeQuery(rawQuery);
				var parts = raw.Split(',');
				query.TimestampUtc = DateTime.Parse(parts[0], CultureInfo.InvariantCulture);
				query.HandlerKey = parts[1];
				query.JobId = Guid.Parse(parts[2]);
				query.FileName = HttpUtility.UrlDecode(parts[3]);
				query.Command = (FileQueryCommand)Enum.Parse(typeof(FileQueryCommand), parts[4]);
			}
			return query;
		}
		static string DecodeQuery(string query)
		{
			if (query.Contains("%"))
				query = HttpUtility.UrlDecode(query);
			byte[] data = Convert.FromBase64String(query);
			int hashLen = 20;
			int mLen = data.Length - hashLen;
			byte[] mbytes = new byte[mLen];
			byte[] hashBytes = new byte[hashLen];
			Array.Copy(data, 0, mbytes, 0, mLen);
			Array.Copy(data, mLen, hashBytes, 0, hashLen);
			byte[] currentHashBytes = new System.Security.Cryptography.SHA1Managed().ComputeHash(mbytes);
			if (BaseHandler.CompareHash(hashBytes, currentHashBytes))
				return UTF8Encoding.UTF8.GetString(mbytes);
			else
				throw new InvalidOperationException("Invalid query request.");
		}
		#endregion
	}
	#endregion
}